﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Net;
using System.IO;

namespace Tools.Framework
{
   public class PostGetHelper
    {
        private static readonly string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
        /// <summary>
        /// 创建GET方式的HTTP请求
        /// </summary>
        /// <param name="url">请求的URL</param>
        /// <param name="timeout">请求的超时时间</param>
        /// <param name="userAgent">请求的客户端浏览器信息，可以为空</param>
        /// <param name="cookies">随同HTTP请求发送的Cookie信息，如果不需要身份验证可以为空</param>
        /// <returns></returns>
        public static HttpWebResponse CreateGetHttpResponse(string url, int? timeout, string userAgent, CookieCollection cookies)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            request.Method = "GET";
            request.UserAgent = DefaultUserAgent;
            if (!string.IsNullOrEmpty(userAgent))
            {
                request.UserAgent = userAgent;
            }
            if (timeout.HasValue)
            {
                request.Timeout = timeout.Value;
            }
            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }
            return request.GetResponse() as HttpWebResponse;
        }
        /// <summary>
        /// 创建POST方式的HTTP请求
        /// </summary>
        /// <param name="url">请求的URL</param>
        /// <param name="parameters">随同请求POST的参数名称及参数值字典</param>
        /// <param name="timeout">请求的超时时间</param>
        /// <param name="userAgent">请求的客户端浏览器信息，可以为空</param>
        /// <param name="requestEncoding">发送HTTP请求时所用的编码</param>
        /// <param name="cookies">随同HTTP请求发送的Cookie信息，如果不需要身份验证可以为空</param>
        /// <returns></returns>
        public static HttpWebResponse CreatePostHttpResponse(string url, IDictionary<string, string> parameters, int? timeout, string userAgent, Encoding requestEncoding, CookieCollection cookies)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (requestEncoding == null)
            {
                throw new ArgumentNullException("requestEncoding");
            }
            HttpWebRequest request = null;
            //如果是发送HTTPS请求
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                request = WebRequest.Create(url) as HttpWebRequest;
                request.ProtocolVersion = HttpVersion.Version11;
            }
            else
            {
                request = WebRequest.Create(url) as HttpWebRequest;
            }
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";

            if (!string.IsNullOrEmpty(userAgent))
            {
                request.UserAgent = userAgent;
            }
            else
            {
                request.UserAgent = DefaultUserAgent;
            }
            if (timeout.HasValue)
            {
                request.Timeout = timeout.Value;
            }
            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }
            //如果需要POST数据
            if (!(parameters == null || parameters.Count == 0))
            {
                StringBuilder buffer = new StringBuilder();
                int i = 0;
                foreach (string key in parameters.Keys)
                {
                    if (i > 0)
                    {
                        buffer.AppendFormat("&{0}={1}", key, parameters[key]);
                    }
                    else
                    {
                        buffer.AppendFormat("{0}={1}", key, parameters[key]);
                    }
                    i++;
                }
                byte[] data = requestEncoding.GetBytes(buffer.ToString());
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
            }
            return request.GetResponse() as HttpWebResponse;
        }
        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受
        }





       public class CreatePostForm
       {

           /// <summary>  
           /// 表单数据项  
           /// </summary>  
           public class FormItemModel
           {
               /// <summary>  
               /// 表单键，request["key"]  
               /// </summary>  
               public string Key { set; get; }
               /// <summary>  
               /// 表单值,上传文件时忽略，request["key"].value  
               /// </summary>  
               public string Value { set; get; }
               /// <summary>  
               /// 是否是文件  
               /// </summary>  
               public bool IsFile
               {
                   get
                   {
                       if (FileContent == null || FileContent.Length == 0)
                           return false;

                       if (FileContent != null && FileContent.Length > 0 && string.IsNullOrWhiteSpace(FileName))
                           throw new Exception("上传文件时 FileName 属性值不能为空");
                       return true;
                   }
               }
               /// <summary>  
               /// 上传的文件名  
               /// </summary>  
               public string FileName { set; get; }
               /// <summary>  
               /// 上传的文件内容  
               /// </summary>  
               public Stream FileContent { set; get; }
           }


           public List<FormItemModel> formItems { get; set; }

           /// <summary>  
           /// Post表单提交（包含提交文件）
           /// </summary>  
           /// <param name="url"></param>  
           /// <param name="formItems">Post表单内容</param>  
           /// <param name="cookieContainer"></param>  
           /// <param name="timeOut">默认20秒</param>  
           /// <param name="encoding">响应内容的编码类型（默认utf-8）</param>  
           /// <returns></returns>  
           public string PostForm(string url,CookieContainer cookieContainer = null, string refererUrl = null, Encoding encoding = null, int timeOut = 20000)
           {
               HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
               #region 初始化请求对象
               request.Method = "POST";
               request.Timeout = timeOut;
               request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
               request.KeepAlive = true;
               request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";
               if (!string.IsNullOrEmpty(refererUrl))
                   request.Referer = refererUrl;
               if (cookieContainer != null)
                   request.CookieContainer = cookieContainer;
               #endregion

               string boundary = "----" + DateTime.Now.Ticks.ToString("x");//分隔符  
               request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
               //请求流  
               var postStream = new MemoryStream();
               #region 处理Form表单请求内容
               //是否用Form上传文件  
               var formUploadFile = formItems != null && formItems.Count > 0;
               if (formUploadFile)
               {
                   //文件数据模板  
                   string fileFormdataTemplate =
                       "\r\n--" + boundary +
                       "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" +
                       "\r\nContent-Type: application/octet-stream" +
                       "\r\n\r\n";
                   //文本数据模板  
                   string dataFormdataTemplate =
                       "\r\n--" + boundary +
                       "\r\nContent-Disposition: form-data; name=\"{0}\"" +
                       "\r\n\r\n{1}";
                   foreach (var item in formItems)
                   {
                       string formdata = null;
                       if (item.IsFile)
                       {
                           //上传文件  
                           formdata = string.Format(
                               fileFormdataTemplate,
                               item.Key, //表单键  
                               item.FileName);
                       }
                       else
                       {
                           //上传文本  
                           formdata = string.Format(
                               dataFormdataTemplate,
                               item.Key,
                               item.Value);
                       }

                       //统一处理  
                       byte[] formdataBytes = null;
                       //第一行不需要换行  
                       if (postStream.Length == 0)
                           formdataBytes = Encoding.UTF8.GetBytes(formdata.Substring(2, formdata.Length - 2));
                       else
                           formdataBytes = Encoding.UTF8.GetBytes(formdata);
                       postStream.Write(formdataBytes, 0, formdataBytes.Length);

                       //写入文件内容  
                       if (item.FileContent != null && item.FileContent.Length > 0)
                       {
                           using (var stream = item.FileContent)
                           {
                               byte[] buffer = new byte[1024];
                               int bytesRead = 0;
                               while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
                               {
                                   postStream.Write(buffer, 0, bytesRead);
                               }
                           }
                       }
                   }
                   //结尾  
                   var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
                   postStream.Write(footer, 0, footer.Length);

               }
               else
               {
                   request.ContentType = "application/x-www-form-urlencoded";
               }
               #endregion

               request.ContentLength = postStream.Length;

               #region 输入二进制流
               if (postStream != null)
               {
                   postStream.Position = 0;
                   //直接写入流  
                   Stream requestStream = request.GetRequestStream();

                   byte[] buffer = new byte[1024];
                   int bytesRead = 0;
                   while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0)
                   {
                       requestStream.Write(buffer, 0, bytesRead);
                   }

                   ////debug  
                   //postStream.Seek(0, SeekOrigin.Begin);  
                   //StreamReader sr = new StreamReader(postStream);  
                   //var postStr = sr.ReadToEnd();  
                   postStream.Close();//关闭文件访问  
               }
               #endregion

               HttpWebResponse response = (HttpWebResponse)request.GetResponse();
               if (cookieContainer != null)
               {
                   response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
               }

               using (Stream responseStream = response.GetResponseStream())
               {
                   using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.UTF8))
                   {
                       string retString = myStreamReader.ReadToEnd();
                       return retString;
                   }
               }
           }  
 
       }

    }
}
